home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 008 / polymusi.arc / POLYMUSI.ASM next >
Encoding:
Assembly Source File  |  1985-07-20  |  3.9 KB  |  149 lines

  1.  
  2. title TRI - 8088 routine CALLed from BASIC   Steve Muenter
  3.  
  4. comment *This routine produces polyphonic music with three
  5.     voices.  The frequencies and durations of the notes
  6.     are passed to this routine in an integer array.
  7.  
  8.     Called from BASIC via:
  9.  
  10.         CALL TRI(TUNE%(0))
  11.  
  12.     Where:
  13.  
  14.         TUNE% is an integer array
  15.  
  16.     TUNE% is treated by TRI as data words with the three most
  17.     significant bits identifying the type of data.    000 causes
  18.     the routine to terminate and return to BASIC.  001 sets
  19.     the duration of play of the voices before being updated.
  20.     010 sets the tempo of the playback.  011 is unused.  100
  21.     sets the period for voice 1 which is slightly louder than
  22.     the rest.  101 sets the period for voice 2.  110 sets the
  23.     period for voice 3.
  24.     *
  25.  
  26. cseg    segment
  27.     assume CS:cseg, DS:cseg, ES:nothing
  28. ;    db    0FDH        ;indicates BLOAD file
  29. ;    dw    0        ;segment--BASIC will use default
  30. ;    dw    0        ;offset--specify in BLOAD command
  31. ;    dw    rtn_len     ;length of the routine
  32.  
  33. spkr_io equ    61H
  34.  
  35. tri    proc    far
  36.     push    bp
  37.     mov    bp,sp
  38.     mov    ax,[bp+6]    ;get address of TUNE%(0) off stack
  39.     sub    ax,2        ;required for first time in sort
  40.     push    ax        ;save on stack
  41.     mov    ax,1FFFH    ;default tempo data
  42.     push    ax        ;save on stack
  43.     push    ax        ;initialize tempo counter
  44.     xor    ax,ax        ;must write 0 into voice count and
  45.     mov    bx,ax        ; data registers
  46.     mov    dx,ax
  47.     mov    si,ax
  48.     mov    bp,ax
  49.     mov    di,ax
  50.     mov    es,ax
  51. ;
  52. ;This section sorts the tune data into the appropriate registers
  53. ;Voice period data is stored in ES for voice 1, DI for voice 2,
  54. ;and SI for voice 3.  The voice period count is stored in BX for
  55. ;voice 1, DX for voice 2, and BP for voice 3.
  56. ;
  57. sort:    push    bx
  58.     push    dx
  59.     push    bp
  60.  
  61. sort_1: mov    bp,sp
  62.     mov    bx,[bp+10]    ;get tune pointer
  63.     add    bx,2        ;point to next tune data
  64.     mov    [bp+10],bx    ;restore updated tune pointer
  65.     mov    ax,[bx]     ;get tune data in AX
  66.     mov    dx,ax        ;make a copy in DX
  67.     and    dx,1FFFH    ;strip off 3 data type bits
  68.     shl    ax,1        ;move msb into carry bit
  69.     jnc    sort_4        ;jump if end, duration, or tempo data
  70.     shl    ax,1        ;move 2nd msb into carry bit
  71.     jc    sort_3        ;jump if voice 3 data
  72.     shl    ax,1        ;move 3rd msb into carry bit
  73.     jc    sort_2        ;jump if voice 2 data
  74.     mov    es,dx        ;store voice 1 data in ES
  75.     jmp    sort_1
  76. sort_2: mov    di,dx        ;store voice 2 data in DI
  77.     jmp    sort_1
  78. sort_3: mov    si,dx        ;store voice 3 data in SI
  79.     jmp    sort_1        ;ignore
  80. sort_4: shl    ax,1        ;move 2nd msb into carry bit
  81.     jnc    sort_6        ;jump if end or duration data
  82.     shl    ax,1
  83.     jnc    sort_5        ;jump if tempo data
  84.     jmp    sort_1        ;ignore
  85. sort_5: mov    [bp+8],dx    ;store tempo
  86.     mov    [bp+6],dx    ;initialize tempo counter
  87.     jmp    sort_1
  88. sort_6: shl    ax,1        ;move 3rd msb into carry
  89.     jc    sort_7        ;jump if duration
  90.     jmp    end
  91. sort_7: mov    cx,dx        ;store duration data
  92.     pop    bp
  93.     pop    dx
  94.     pop    bx
  95.     cli            ;turn off interrupts during play
  96. loop:    pop    ax        ;get current tempo count
  97.     dec    ax        ;subtract 1
  98.     push    ax        ;restore tempo count
  99.     jnz    play        ;jump if some tempo remains
  100.     pop    ax        ;reset tempo counter
  101.     pop    ax
  102.     push    ax
  103.     push    ax
  104.     loop    play        ;decrement duration counter
  105.     sti            ;turn ints back on during sort
  106.     jmp    sort        ;get new tune data if duration up
  107. ;
  108. ;This routine plays the notes until the duration counter in CX
  109. ;reaches zero.    At that time, the new data is sorted.
  110. ;
  111. play:    add    bx,si        ;add voice 3 data to count
  112.     rol    bx,1        ;get msb of voice 3 count
  113.     mov    al,12H        ;keeps keyboard clk on and
  114.     rcl    al,1        ; casette motor relay off
  115.     rcl    al,1
  116.     out    spkr_io,al    ;output voice 3 state to speaker
  117.     ror    bx,1        ;restore bx to original state
  118.     add    dx,di        ;add voice 2 data to count
  119.     rol    dx,1
  120.     mov    al,12H
  121.     rcl    al,1
  122.     rcl    al,1
  123.     out    spkr_io,al
  124.     ror    dx,1
  125.     mov    ax,es
  126.     add    bp,ax        ;add voice 1 data to count
  127.     rol    bp,1
  128.     mov    al,12H
  129.     rcl    al,1
  130.     rcl    al,1
  131.     out    spkr_io,al
  132.     ror    bp,1
  133.     jmp    loop
  134. end:    add    sp,12
  135.     pop    bp
  136.     mov    ax,cs
  137.     mov    es,ax
  138.     ret    2
  139. tri    endp
  140. rtn_len equ    $-tri        ;length of routine for header
  141. cseg    ends
  142.     end    tri
  143. 
  144.     bp
  145.     mov    ax,cs
  146.     mov    es,ax
  147.     ret    2
  148. tri    endp
  149. rtn_len equ    $-tri        ;le